package IO;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
/*
为了解决依赖继承会导致子类数量失控的问题，JDK首先将InputStream分为两大类：

一类是直接提供数据的基础InputStream，例如：

-FileInputStream
-ByteArrayInputStream
-ServletInputStream
 ...
一类是提供额外附加功能的InputStream，例如：

-BufferedInputStream
-DigestInputStream
-CipherInputStream
 ...
当我们需要给一个“基础”InputStream附加各种功能时，我们先确定这个能提供数据源的InputStream，因为我们需要的数据总得来自某个地方，例如，FileInputStream，数据来源自文件：

InputStream file = new FileInputStream("test.gz");
紧接着，我们希望FileInputStream能提供缓冲的功能来提高读取的效率，因此我们用BufferedInputStream包装这个InputStream，得到的包装类型是BufferedInputStream，但它仍然被视为一个InputStream：

InputStream buffered = new BufferedInputStream(file);
最后，假设该文件已经用gzip压缩了，我们希望直接读取解压缩的内容，就可以再包装一个GZIPInputStream：

InputStream gzip = new GZIPInputStream(buffered);
无论我们包装多少次，得到的对象始终是InputStream，我们直接用InputStream来引用它，就可以正常读取：

┌─────────────────────────┐
│GZIPInputStream          │
│┌───────────────────────┐│
││BufferedFileInputStream││
││┌─────────────────────┐││
│││   FileInputStream   │││
││└─────────────────────┘││
│└───────────────────────┘│
└─────────────────────────┘
上述这种通过一个“基础”组件再叠加各种“附加”功能组件的模式，称之为Filter模式（或者装饰器模式：Decorator）。它可以让我们通过少量的类
来实现各种功能的组合：

                 ┌─────────────┐
                 │ InputStream │
                 └─────────────┘
                       ▲ ▲
┌────────────────────┐ │ │ ┌─────────────────┐
│  FileInputStream   │─┤ └─│FilterInputStream│
└────────────────────┘ │   └─────────────────┘
┌────────────────────┐ │     ▲ ┌───────────────────┐
│ByteArrayInputStream│─┤     ├─│BufferedInputStream│
└────────────────────┘ │     │ └───────────────────┘
┌────────────────────┐ │     │ ┌───────────────────┐
│ ServletInputStream │─┘     ├─│  DataInputStream  │
└────────────────────┘       │ └───────────────────┘
                             │ ┌───────────────────┐
                             └─│CheckedInputStream │
                               └───────────────────┘
类似的，OutputStream也是以这种模式来提供各种功能：

                  ┌─────────────┐
                  │OutputStream │
                  └─────────────┘
                        ▲ ▲
┌─────────────────────┐ │ │ ┌──────────────────┐
│  FileOutputStream   │─┤ └─│FilterOutputStream│
└─────────────────────┘ │   └──────────────────┘
┌─────────────────────┐ │     ▲ ┌────────────────────┐
│ByteArrayOutputStream│─┤     ├─│BufferedOutputStream│
└─────────────────────┘ │     │ └────────────────────┘
┌─────────────────────┐ │     │ ┌────────────────────┐
│ ServletOutputStream │─┘     ├─│  DataOutputStream  │
└─────────────────────┘       │ └────────────────────┘
                              │ ┌────────────────────┐
                              └─│CheckedOutputStream │
                                └────────────────────┘
*/
/*
//压缩单个文件
public class 使用Zip {
	public static void main(String[] args) throws IOException {
		File file = new File("d:\\test.txt");
		try (FileInputStream fis = new FileInputStream(file);
				ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("d:\\my.zip"))) {
			//1. 创建压缩文件中的条目
			ZipEntry entry = new ZipEntry(file.getName());
			//2. 将创建好的条目加入到压缩文件中
			zos.putNextEntry(entry);
			//3. 写入当前条目所对应的具体内容
			byte[] buff = new byte[2048];
			int len = 0;
			while ((len = fis.read(buff)) != -1) {
				zos.write(buff, 0, len);
			}
		}
	}
}
*/
/*
//解压单个文件
public class 使用Zip {
	public static void main(String[] args) throws IOException{
		InputStream is = null;
		try (//ZipFile zf = new ZipFile("d:\\my.zip");
   		 FileOutputStream fos = new FileOutputStream("d:\\unzip.txt");
   		 ZipInputStream zis = new ZipInputStream(new FileInputStream("d:\\my.zip"))){
			 //1. 从压缩文件中获取一个条目
			 ZipEntry entry = zis.getNextEntry();
			 //2. 获得该条目对象的数据流
			 //is = zf.getInputStream(entry);
			 byte[] buff = new byte[1024];
			 int len = 0;
			 while ((len = zis.read(buff)) != -1) {
				 System.out.println(len+entry.getName());//1024test.txt
				 fos.write(buff, 0, len);
			 }
		 }
	}
}
*/
/**
 * 目录压缩
 * zipFileName:压缩后zip文件的路径
 * inputFile:需要压缩的源目录；
 * */
/*
public class 使用Zip {
	public static void main(String[] args) throws IOException{
		String zipFileName="f:\\zipfile";//压缩至d:\zipfile目录
		String inputFile="f:\\文本文件";//需要压缩的目录
		File file = new File(inputFile);
	
		try (FileOutputStream fos = new FileOutputStream(zipFileName);
			ZipOutputStream out = new ZipOutputStream(fos)){
			zipDir(out,file,inputFile);
			//out.close();
			System.out.println("over!!");
		}
	}
	//递归遍历子目录和文件，进行压缩
	static void zipDir(ZipOutputStream out, File file, String base) throws IOException {
	
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			out.putNextEntry(new ZipEntry(base+"/"));//ZipEntry对象：“/”结尾，则为文件夹,否则为文件。
			base = base.length()==0?"":base+"/";
			System.out.println(base+"---"+file.getCanonicalPath());
			for (int i = 0; i < files.length; i++) {
				//进行递归
				zipDir(out,files[i], base+files[i].getName());
			}
		}else {
			out.putNextEntry(new ZipEntry(base));
			FileInputStream fis = new FileInputStream(file);
			System.out.println(file.getName());
			int len = 0;
			while((len = fis.read()) != -1){
				//写入到目标zip中
				out.write(len);
			}
			fis.close();
		}
	}
}
*/
///*
// * 解压缩目录
// * zipFileName:需要解压缩的zip文件
// * outputDirectory:解压缩后文件所放路径
// */

public class 使用Zip {
	public static void main(String[] args) throws IOException{
		String zipFileName="f:\\zipfile";
		String outputDirectory="f:\\zipfilepath";
		File file=new File(outputDirectory);
		file.mkdir();
		try (
			FileInputStream fis = new FileInputStream(zipFileName);
			ZipInputStream zis = new ZipInputStream(fis)) {
			unZip(zis,file,outputDirectory);}
		System.out.println("over!!");
		
	}	
	static void unZip(ZipInputStream in, File file,String base) throws IOException {
		ZipEntry zipEntry=null;	
		while((zipEntry = in.getNextEntry()) != null){
			String name = zipEntry.getName();
			//ZipEntry对象：“/”结尾，则为文件夹,否则为文件。
			name = name.substring(2,name.length()).replace("/","\\");//去除目录项目的尾部标识‘/’，换成‘\\’
			//System.out.println("name: "+name);
			File f = new File(base+File.separator+name);
			//System.out.println("绝对路径： "+f.getCanonicalPath());
			System.out.println("zipEntry： "+zipEntry.getName());
			if (zipEntry.isDirectory()) {
				f.mkdir();
				//System.out.println("zipEntry： "+zipEntry.getName());
				unZip(in,f,base);
			}else {
				f.createNewFile();
				try(FileOutputStream fos = new FileOutputStream(f)){
					int len = 0;
					while((len = in.read()) != -1){//每次读一个字节
						//写入到目标文件中
						fos.write(len);
					}
				}
			}
		}
	}
}
